using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using RaisingStudio.Common.Xml;
using RaisingStudio.Data.Common.Configuration;
using System.Data;

namespace RaisingStudio.Data.Common
{
    public sealed class CommandManager
    {
        #region Instance
        //public static readonly CommandManager Instance = new CommandManager();
        private static volatile CommandManager _instance = null;
        public static CommandManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (typeof(CommandManager))
                    {
                        if (_instance == null)
                        {
                            _instance = new CommandManager();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion

        private Dictionary<string, Command> commands;

        public const string COMMANDS_FILE_NAME = "commands.config";

        public const string COMMAND_NAME = "name";
        public const string COMMAND_TYPE = "commandType";
        public const string PARAMETERPREFIX = "parameterPrefix";

        private string parameterPrefix;
        public string ParameterPrefix
        {
            get
            {
                return parameterPrefix;
            }
        }

        private CommandManager()
        {
            commands = new Dictionary<string, Command>();
            XmlDocument xmlDocument = Resources.GetConfigAsXmlDocument(COMMANDS_FILE_NAME);
            AddCommands(xmlDocument);
        }

        private object commands_lock = new object();

        public void AppendCommands(string baseDirectory)
        {
            XmlDocument xmlDocument = Resources.GetConfigAsXmlDocument(baseDirectory, COMMANDS_FILE_NAME);
            lock (this.commands_lock)
            {
                AddCommands(xmlDocument);
            }
        }

        private void AddCommands(XmlDocument xmlDocument)
        {
            if ((xmlDocument != null) && (xmlDocument.DocumentElement != null))
            {
                System.Xml.XmlElement xmlElement = xmlDocument.DocumentElement;
                if (xmlElement.Attributes[PARAMETERPREFIX] != null)
                {
                    parameterPrefix = xmlElement.Attributes[PARAMETERPREFIX].Value;
                }
                else
                {
                    parameterPrefix = "@";
                }
                foreach (System.Xml.XmlNode childXmlNode in xmlElement)
                {
                    if (childXmlNode is System.Xml.XmlElement)
                    {
                        System.Xml.XmlElement childXmlElement = childXmlNode as System.Xml.XmlElement;
                        Command command = new Command();
                        if (childXmlElement.Attributes[COMMAND_NAME] != null)
                        {
                            command.Name = childXmlElement.Attributes[COMMAND_NAME].Value;
                        }
                        if (childXmlElement.Attributes[COMMAND_TYPE] != null)
                        {
                            command.CommandType = (CommandType)System.Enum.Parse(typeof(CommandType), childXmlElement.Attributes[COMMAND_TYPE].Value, false);
                        }

                        string commandText = childXmlElement.InnerText;
                        if (!string.IsNullOrEmpty(commandText))
                        {
                            commandText = commandText.Trim();
                        }
                        command.CommandText = commandText;

                        commands.Add(command.Name, command);
                    }
                }
            }
        }


        public CommonCommand GetCommand(string name)
        {
            Command command = null;
            lock (commands_lock)
            {
                command = commands[name];
            }
            if (command != null)
            {
                CommonCommand commonCommand = new CommonCommand();
                commonCommand.ParameterPrefix = parameterPrefix;
                commonCommand.CommandType = command.CommandType;
                commonCommand.CommandText = command.CommandText;
                return commonCommand;
            }
            return null;
        }
    }
}
